package com.train.gateway.filter;

import cn.hutool.core.text.AntPathMatcher;
import com.train.common.enums.impl.SysExceptionEnums;
import com.train.common.resp.CommonResp;
import com.train.common.utils.jwt.JwtUtils;
import com.train.gateway.common.utils.io.IoUtils;
import io.micrometer.common.util.StringUtils;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.annotation.Order;
import org.springframework.http.HttpHeaders;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.util.List;
import java.util.Map;

@Component
@Order(0)
@Slf4j
@ConfigurationProperties(prefix = "gateway")
@Setter
public class IdentityValidFilter implements GlobalFilter {

    private List<String> excludedPaths;

    private static final AntPathMatcher PATH_MATCHER = new AntPathMatcher();

    /**
     * token校验
     * @param exchange
     * @param chain
     * @return
     */
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        ServerHttpResponse response = exchange.getResponse();
        ServerHttpRequest request = exchange.getRequest();

        //排除不校验的接口
        String requestPath = request.getURI().getPath();
        for (String excludedPath : excludedPaths) {
            if (PATH_MATCHER.match(excludedPath, requestPath)) {
                return chain.filter(exchange);
            }
        }

        //校验token是否为空
        HttpHeaders headers = request.getHeaders();
        Map<String, String> singleValueMap = headers.toSingleValueMap();
        String token = singleValueMap.get("access-token");
        if (StringUtils.isBlank(token) || !token.startsWith("Bearer ")) {
            log.error("token为空");
            SysExceptionEnums tokenInvalid = SysExceptionEnums.EXP_TOKEN_INVALID;
            return writeError(response, tokenInvalid);
        }
        token = token.substring(7);

        //验证token签名是否有效, 时间是否过期
        if (!JwtUtils.validate(token)) {
            log.error("token签名无效");
            SysExceptionEnums tokenInvalid = SysExceptionEnums.EXP_TOKEN_INVALID;
            return writeError(response, tokenInvalid);
        }

        log.info("token验证成功");
        return chain.filter(exchange);
    }

    /**
     * 错误信息返回
     * @param response
     * @param sysExceptionEnums
     * @return
     */
    public Mono<Void> writeError(ServerHttpResponse response, SysExceptionEnums sysExceptionEnums) {
        log.error(sysExceptionEnums.getMessage());
        CommonResp error = CommonResp.error(sysExceptionEnums.getCode(), sysExceptionEnums.getMessage());
        return IoUtils.write(response, error);
    }
}
